//
//  ViewController.m
//  KeyboardMonitorByCGEvent
//
//  Created by flynn on 2025/6/16.
//

#import "ViewController.h"
#import <CoreGraphics/CoreGraphics.h>
#import <Carbon/Carbon.h> // 用于 keyCode 转字符
#import <AppKit/AppKit.h>

NSString* getKeyNameWithKeyCode(int iKeyCode)
{
    NSDictionary *dicKeyCode = @{
        @"a":[NSNumber numberWithInt:kVK_ANSI_A],
        @"s":[NSNumber numberWithInt:kVK_ANSI_S],
        @"d":[NSNumber numberWithInt:kVK_ANSI_D],
        @"f":[NSNumber numberWithInt:kVK_ANSI_F],
        @"h":[NSNumber numberWithInt:kVK_ANSI_H],
        @"g":[NSNumber numberWithInt:kVK_ANSI_G],
        @"z":[NSNumber numberWithInt:kVK_ANSI_Z],
        @"x":[NSNumber numberWithInt:kVK_ANSI_X],
        @"c":[NSNumber numberWithInt:kVK_ANSI_C],
        @"v":[NSNumber numberWithInt:kVK_ANSI_V],
        @"b":[NSNumber numberWithInt:kVK_ANSI_B],
        @"q":[NSNumber numberWithInt:kVK_ANSI_Q],
        @"w":[NSNumber numberWithInt:kVK_ANSI_W],
        @"e":[NSNumber numberWithInt:kVK_ANSI_E],
        @"r":[NSNumber numberWithInt:kVK_ANSI_R],
        @"y":[NSNumber numberWithInt:kVK_ANSI_Y],
        @"t":[NSNumber numberWithInt:kVK_ANSI_T],
        @"o":[NSNumber numberWithInt:kVK_ANSI_O],
        @"u":[NSNumber numberWithInt:kVK_ANSI_U],
        @"i":[NSNumber numberWithInt:kVK_ANSI_I],
        @"p":[NSNumber numberWithInt:kVK_ANSI_P],
        @"l":[NSNumber numberWithInt:kVK_ANSI_L],
        @"j":[NSNumber numberWithInt:kVK_ANSI_J],
        @"k":[NSNumber numberWithInt:kVK_ANSI_K],
        @"m":[NSNumber numberWithInt:kVK_ANSI_M],
        @"n":[NSNumber numberWithInt:kVK_ANSI_N],
        @"1":[NSNumber numberWithInt:kVK_ANSI_1],
        @"2":[NSNumber numberWithInt:kVK_ANSI_2],
        @"3":[NSNumber numberWithInt:kVK_ANSI_3],
        @"4":[NSNumber numberWithInt:kVK_ANSI_4],
        @"5":[NSNumber numberWithInt:kVK_ANSI_5],
        @"6":[NSNumber numberWithInt:kVK_ANSI_6],
        @"7":[NSNumber numberWithInt:kVK_ANSI_7],
        @"8":[NSNumber numberWithInt:kVK_ANSI_8],
        @"9":[NSNumber numberWithInt:kVK_ANSI_9],
        @"0":[NSNumber numberWithInt:kVK_ANSI_0],
        @"f1":[NSNumber numberWithInt:kVK_F1],
        @"f2":[NSNumber numberWithInt:kVK_F2],
        @"f3":[NSNumber numberWithInt:kVK_F3],
        @"f4":[NSNumber numberWithInt:kVK_F4],
        @"f5":[NSNumber numberWithInt:kVK_F5],
        @"f6":[NSNumber numberWithInt:kVK_F6],
        @"f7":[NSNumber numberWithInt:kVK_F7],
        @"f8":[NSNumber numberWithInt:kVK_F8],
        @"f9":[NSNumber numberWithInt:kVK_F9],
        @"f10":[NSNumber numberWithInt:kVK_F10],
        @"f11":[NSNumber numberWithInt:kVK_F11],
        @"f12":[NSNumber numberWithInt:kVK_F12],
        @"f13":[NSNumber numberWithInt:kVK_F13],
        @"f14":[NSNumber numberWithInt:kVK_F14],
        @"f15":[NSNumber numberWithInt:kVK_F15],
        @"f16":[NSNumber numberWithInt:kVK_F16],
        @"f17":[NSNumber numberWithInt:kVK_F17],
        @"f18":[NSNumber numberWithInt:kVK_F18],
        @"f19":[NSNumber numberWithInt:kVK_F19],
        @"f20":[NSNumber numberWithInt:kVK_F20],
        @"ESC":[NSNumber numberWithInt:kVK_Escape],
        @"Numpad0":[NSNumber numberWithInt:kVK_ANSI_Keypad0],
        @"Numpad1":[NSNumber numberWithInt:kVK_ANSI_Keypad1],
        @"Numpad2":[NSNumber numberWithInt:kVK_ANSI_Keypad2],
        @"Numpad3":[NSNumber numberWithInt:kVK_ANSI_Keypad3],
        @"Numpad4":[NSNumber numberWithInt:kVK_ANSI_Keypad4],
        @"Numpad5":[NSNumber numberWithInt:kVK_ANSI_Keypad5],
        @"Numpad6":[NSNumber numberWithInt:kVK_ANSI_Keypad6],
        @"Numpad7":[NSNumber numberWithInt:kVK_ANSI_Keypad7],
        @"Numpad8":[NSNumber numberWithInt:kVK_ANSI_Keypad8],
        @"Numpad9":[NSNumber numberWithInt:kVK_ANSI_Keypad9],
        @"Backspace":[NSNumber numberWithInt:kVK_Space],
    };

    for (NSString* key in dicKeyCode.allKeys) {
        if ([[dicKeyCode objectForKey:key] intValue] == iKeyCode)
            return key;
    }
    return @"";
}

// 回调函数：处理键盘事件
CGEventRef myKeyboardEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {
    if (type == kCGEventKeyDown) {
        CGKeyCode keyCode = (CGKeyCode)CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode);
        CGEventFlags flags = CGEventGetFlags(event);
        NSMutableString* strResult = [NSMutableString string];
        if (flags& kCGEventFlagMaskAlternate) [strResult appendString:@"alt/option " ];
        if (flags & kCGEventFlagMaskCommand) [strResult appendString:@"command " ];
        if (flags & kCGEventFlagMaskShift) [strResult appendString:@"shift " ];
//        if (flags & NSEventModifierFlagCapsLock) [strResult appendString:@"capslock " ];
        if (flags & kCGEventFlagMaskControl) [strResult appendString:@"ctrl " ];
        // 打印信息
        NSLog(@"key:%@ %@ ",strResult,getKeyNameWithKeyCode(keyCode));
    }

    return event; // 返回原事件，允许继续传递
}

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    // Do any additional setup after loading the view.
}
- (IBAction)onStart:(id)sender {
    CFMachPortRef eventTap = CGEventTapCreate(
                kCGHIDEventTap,             // tap point
                kCGHeadInsertEventTap,      // placement
                0,                          // options
                (1 << kCGEventKeyDown),     // events of interest
                myKeyboardEventCallback,    // callback function
                NULL                        // user info
            );

            if (!eventTap) {
                NSLog(@"❌ 无法创建事件钩子，请检查辅助功能权限是否已开启");
                return ;
            }

            // 创建 RunLoop Source 并添加到主运行循环
            CFRunLoopSourceRef runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0);
            CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);
            CGEventTapEnable(eventTap, true);

            NSLog(@"✅ 已成功启动全局键盘监听器。按下任意键查看日志...");

            // 启动 RunLoop（保持程序运行）
//            [[NSRunLoop currentRunLoop] run];
}


- (void)setRepresentedObject:(id)representedObject {
    [super setRepresentedObject:representedObject];

    // Update the view, if already loaded.
}


@end
